<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020/4/18
 * Time: 16:45
 */
require_once '../../include/vendor/autoload.php';
require_once 'ChatManager.php';
class SwooleWebsocktServeClasses{
    public $config = array(
        'host' => '0.0.0.0',
        'port'=>9502
    );
    public $serv;//websocket
    public $redis_client;//redis
    public $client_list = array();
    public $chat_manager;//聊天管理

    /**
     *
     * SwooleWebsocktServeClasses constructor.
     * @param array $config
     */
    public function __construct(array $config)
    {
        $this->config = $config;
        $obj = $this;
        $this->redis_client = new Predis\Client();
        $this->chat_manager = new ChatManager();
//创建websocket服务器对象，监听0.0.0.0:9502端口
//        $ws = new Swoole\WebSocket\Server($config['host'],$config['port']);
//        $ws = new swoole_websocket_server($config['host'], $config['port'],SWOOLE_PROCESS,SWOOLE_SOCK_TCP | SWOOLE_SSL);
        $ws = new swoole_websocket_server($config['host'], $config['port']);
        $this->serv = $ws;
//设置异步任务的工作进程数量
        if(isset($config['task_worker_num'])) {
            $ws->set(['task_worker_num' => $config['task_worker_num']]);
        }
//        $ws->set([
//                'ssl_cert_file' => '/www/wwwroot/test.richesmeapp.com/include/ssl/sslcert.pem',
//                'ssl_key_file' => '/www/wwwroot/test.richesmeapp.com/include/ssl/sslkey.key',
//            ]
//        );

//监听WebSocket连接打开事件
        $ws->on('open', [$obj,'open']);

//监听WebSocket消息事件
        $ws->on('message',  [$obj,'message']);

//处理异步任务(此回调函数在task进程中执行)
        $ws->on('task',  [$obj,'task']);

//处理异步任务的结果(此回调函数在worker进程中执行)
        $ws->on('finish',  [$obj,'finish']);

//监听WebSocket连接关闭事件
        $ws->on('close',  [$obj,'close']);

        $ws->start();
    }

    /**
     * 客户端连接
     * @param $ws
     * @param $request
     */
    public function open($ws, $request){

        $ws->push($request->fd, "hello, welcome\n");


    }

    /**
     * 接受消息
     * @param $ws
     * @param $frame
     */
    public function message($ws, $frame){
        echo "Message: {$frame->data}\n";
//        $ws->push($frame->fd, "server: {$frame->data}");
        //投递异步任务
        $data = $frame->data;
        $fd = $frame->fd;
        $this->filterMessage($data,$fd);
    }

    /**
     * 过滤发送内容，分发
     * @param $data
     *
     * {
    "type": "chat",
    "user_level": "0",
    "username": "撒大幅",
    "img_sl": "https;//sdfasdf",
    "user_id": "1",
    "chat_room_id": "1",//房间id
    "content": "123123",
    "m_type": "activity"
    }
     *
     *
     *
     */
    private function filterMessage($data,$fd){
        $res=$this->chat_manager->filtraMessage($data, $fd);
        $task_id = $this->serv->task($res);
        echo "Dispatch AsyncTask: id=$task_id\n";
    }

    /**
     * 异步执行任务
     * @param $serv
     * @param $task_id
     * @param $from_id
     * @param $data
     */
    public function task($serv, $task_id, $from_id, $data)
    {
        var_dump($data);
        $data= (array)json_decode($data);
        $send_fd = $data['send_fd']??0;
        $send_data = $data['content']??'';
        echo "New AsyncTask[id=$task_id]  data:{$send_data}".PHP_EOL;
        var_dump($data['type']);
        //获得这个房间的所有连接
        $connetions = $this->chat_manager->getRoomidFd($data['chat_room_id']);
        if($data['type']=='join'){//给进入的人发放聊天记录和房间配置
            echo "执行进入房间任务join，来源fd：{$send_fd}".PHP_EOL;
            $this->serv->push($send_fd, json_encode($data,JSON_UNESCAPED_UNICODE));
            //给其他人发送消息 有新人进入
            unset($data['chat_room_msg_list']);
//            $data=array_values($data);
            $data['type'] = 'new_watch_join';
            foreach ($connetions as $item_fd) {
                $is_established=$this->checkConnectAlife($item_fd);
                if($is_established) {
                    $this->serv->push($item_fd, json_encode($data, JSON_UNESCAPED_UNICODE));
                }
            }
        }else {
            //返回任务执行的结果

            foreach ($connetions as $item_fd) {
                $is_established=$this->checkConnectAlife($item_fd);
                if($is_established) {
                    echo "执行发送任务，目标fd：{$item_fd}, 来源fd：{$send_fd}" . PHP_EOL;
                    $item_fd = (int)$item_fd;
                    if ($item_fd != $send_fd) {
                        $this->serv->push($item_fd, json_encode($data, JSON_UNESCAPED_UNICODE));
                    }
                }

            }
        }
        if($data['type']=='chat') {
            //给发送者返回该记录id
            $data['type'] = 'chat_return';
            $this->serv->push($send_fd, json_encode($data, JSON_UNESCAPED_UNICODE));
        }

        $serv->finish("finish -> OK");
    }

    /**
     * 执行任务完成回调
     * @param $serv
     * @param $task_id
     * @param $data
     */
    public function finish($serv, $task_id, $data)
    {
        echo "AsyncTask[$task_id] Finish: $data".PHP_EOL;
    }

    /**
     * 客户端关闭
     * @param $ws
     * @param $fd
     */
    public function close($ws, $fd){
        echo "client-{$fd} is closed\n";
        $res=$this->chat_manager->outChatRoom($fd);
        $data = json_encode($res, JSON_UNESCAPED_UNICODE);
        $this->serv->task($data);
    }

    /**
     * 判断是否是有效连接，不是就退出房间
     * @param $fd
     * @return bool
     */
    public function checkConnectAlife($fd)
    {
        $is_established=$this->serv->isEstablished($fd);
        if($is_established) {
            return true;
        }else{
            return true;

            $this->chat_manager->outChatRoom($fd);
            return false;
        }
    }
}
